import { addReadyProduct } from '../core/ReadyProducts'
import { schedule } from '../core/Scheduler'
import { currentTime } from '../core/SimulationClock'
import { messageTransfer } from '../messaging/MessageTransfer'
import BaseStation from './BaseStation'
import Product from './Product'

class Workstation extends BaseStation {
  //加工时间
  processTime: number | string
  //不良品率
  defectRate: number
  //当前正在加工的产品
  currentProduct: Product | null = null
  //故障率
  faultRate: number = 0

  constructor(
    id: string,
    name: string,
    x: number,
    y: number,
    width = 100,
    height = 100,
    processTime: number | string,
    defectRate: number = 0,
    faultRate: number = 0
  ) {
    super(id, name, x, y, width, height)
    this.processTime = processTime
    this.defectRate = defectRate
    this.faultRate = faultRate
  }

  public canReceiveProduct(): boolean {
    return this.status === 'idle'
  }

  //接收到产品，进行加工前的准备工作
  onProductReceived(product: Product): void {
    messageTransfer('product', 'move', { targetId: this.id, productId: product.id })
    messageTransfer('product', 'startProcessing', { targetId: this.id, productId: product.id })
    this.tryProcess(product)
  }

  tryProcess(product: Product, retry = false): void {
    this.currentProduct = product
    this.setStatus('processing')
    if (Math.random() < this.faultRate && !retry) {
      messageTransfer('style', null, {
        targetId: this.id,
        style: {
          backgroundColor: '#FFB1B16B'
        }
      })
      messageTransfer('product', 'finishProcessing', { targetId: this.id, productId: product.id })
      this.setStatus('fault')
      return
    }

    let time = 0
    if (typeof this.processTime === 'string') {
      time = new Function(this.processTime)()
    } else {
      time = this.processTime
    }
    console.log(`[${currentTime}] ${this.name} 开始加工 ${product.id}，预计需要时间 ${time}`)
    schedule(time, () => this.finishProcessing(product), `${this.id} process finish ${product.id}`)
  }

  finishProcessing(product: Product): void {
    if (Math.random() < this.defectRate) {
      console.log(`[${currentTime}] ❌ ${this.name} 报废产品 ${product.id}`)
      messageTransfer('style', null, {
        targetId: this.id,
        style: {
          backgroundColor: '#FFDEB16B'
        }
      })
      messageTransfer('product', 'finishProcessing', { targetId: this.id, productId: product.id })
      this.setStatus('clearance')
      return
    }
    messageTransfer('product', 'finishProcessing', { targetId: this.id, productId: product.id })
    //产品加工完毕，尝试派发产品
    this.setStatus('block')
  }

  //向下游派发产品
  public tryDispatchCurrentProduct(): void {
    if (!this.currentProduct) return
    console.log(`[${currentTime}] ${this.name} 尝试派发产品 ${this.currentProduct.id}`)
    const productId = this.currentProduct.id
    for (const next of this.nextStations) {
      if (next.canReceiveProduct(this.id, this.currentProduct)) {
        //当前产品添加到就绪产品队列中
        addReadyProduct(this.currentProduct)
        this.currentProduct = null

        next.receiveReadyProduct(productId)
        this.setStatus('idle')
        break
      }
    }
  }

  public eventWindow(eventType: 'status' | 'rework' | 'delProduct', param: any): void {
    if (eventType === 'status') {
      this.setStatus(param)
    } else if (eventType === 'rework' && this.currentProduct) {
      messageTransfer('product', 'startProcessing', {
        targetId: this.id,
        productId: this.currentProduct.id
      })
      this.tryProcess(this.currentProduct, true)
    } else if (eventType === 'delProduct' && this.currentProduct) {
      messageTransfer('product', 'recycle', {
        targetId: this.id,
        productId: this.currentProduct.id
      })
    }
  }
}

export default Workstation
